<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>24×24 Icon Editor</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
      background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
      min-height: 100vh;
      padding: 2rem;
    }

    .container {
      max-width: 1200px;
      margin: 0 auto;
      background: white;
      border-radius: 1rem;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1);
      padding: 2rem;
    }

    .header {
      margin-bottom: 2rem;
    }

    h1 {
      font-size: 2rem;
      color: #1e293b;
      margin-bottom: 0.5rem;
      display: flex;
      align-items: center;
      gap: 0.75rem;
    }

    .subtitle {
      color: #64748b;
      margin-bottom: 0.5rem;
    }

    .save-note {
      color: #2563eb;
      font-size: 0.875rem;
    }

    .main-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 2rem;
    }

    @media (max-width: 768px) {
      .main-grid {
        grid-template-columns: 1fr;
      }
    }

    .canvas-area {
      display: flex;
      flex-direction: column;
      gap: 1rem;
    }

    .canvas-wrapper {
      background: #f8fafc;
      border-radius: 0.75rem;
      padding: 1.5rem;
      border: 2px solid #e2e8f0;
    }

    #displayCanvas {
      border: 2px solid #cbd5e1;
      border-radius: 0.5rem;
      cursor: crosshair;
      background: white;
      box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05);
      image-rendering: pixelated;
      display: block;
      width: 100%;
      max-width: 384px;
      height: auto;
      aspect-ratio: 1;
    }

    .canvas-hint {
      font-size: 0.875rem;
      color: #64748b;
      text-align: center;
      margin-top: 0.75rem;
    }

    .panel {
      background: #f8fafc;
      border-radius: 0.75rem;
      padding: 1rem;
      border: 2px solid #e2e8f0;
      margin-bottom: 1.5rem;
    }

    .panel h3 {
      font-size: 1rem;
      color: #475569;
      margin-bottom: 0.75rem;
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }

    .btn {
      padding: 0.75rem 1.5rem;
      border: none;
      border-radius: 0.5rem;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.2s;
      font-size: 0.875rem;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 0.5rem;
    }

    .btn:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }

    .btn-primary {
      background: #2563eb;
      color: white;
      box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
    }

    .btn-primary:hover:not(:disabled) {
      background: #1d4ed8;
    }

    .btn-success {
      background: #16a34a;
      color: white;
      box-shadow: 0 4px 12px rgba(22, 163, 74, 0.3);
      width: 100%;
    }

    .btn-success:hover {
      background: #15803d;
    }

    .btn-danger {
      background: #fef2f2;
      color: #b91c1c;
      border: 2px solid #fecaca;
      width: 100%;
    }

    .btn-danger:hover {
      background: #fee2e2;
    }

    .btn-secondary {
      background: white;
      color: #475569;
      border: 2px solid #cbd5e1;
    }

    .btn-secondary:hover {
      background: #f1f5f9;
    }

    .btn-secondary.active {
      background: #2563eb;
      color: white;
      box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
    }

    .tool-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 0.5rem;
    }

    .color-picker-wrapper {
      display: flex;
      gap: 0.75rem;
      align-items: center;
      margin-bottom: 0.75rem;
    }

    #colorPicker {
      width: 4rem;
      height: 4rem;
      border: 2px solid #cbd5e1;
      border-radius: 0.5rem;
      cursor: pointer;
    }

    #colorInput {
      flex: 1;
      padding: 0.5rem;
      border: 2px solid #cbd5e1;
      border-radius: 0.5rem;
      font-family: monospace;
      font-size: 0.875rem;
    }

    .preset-colors {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      gap: 0.5rem;
    }

    .color-btn {
      width: 100%;
      aspect-ratio: 1;
      border: 2px solid #cbd5e1;
      border-radius: 0.5rem;
      cursor: pointer;
      transition: all 0.2s;
    }

    .color-btn:hover {
      transform: scale(1.05);
    }

    .color-btn.active {
      border-color: #2563eb;
      transform: scale(1.1);
      box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
    }

    .emoji-grid {
      display: grid;
      grid-template-columns: repeat(6, 1fr);
      gap: 0.5rem;
      margin-top: 0.75rem;
    }

    .emoji-btn {
      font-size: 1.5rem;
      padding: 0.5rem;
      background: white;
      border: none;
      border-radius: 0.5rem;
      cursor: pointer;
      transition: all 0.2s;
    }

    .emoji-btn:hover {
      background: #e2e8f0;
      transform: scale(1.1);
    }

    .emoji-btn.more {
      display: flex;
      align-items: center;
      justify-content: center;
      border: 2px solid #cbd5e1;
      color: #64748b;
      font-size: 1rem;
    }

    .modal {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(0, 0, 0, 0.5);
      z-index: 1000;
      align-items: center;
      justify-content: center;
      padding: 1rem;
    }

    .modal.show {
      display: flex;
    }

    .modal-content {
      background: white;
      border-radius: 0.75rem;
      padding: 1.5rem;
      max-width: 28rem;
      width: 100%;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    }

    .modal-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 1rem;
    }

    .modal-header h3 {
      font-size: 1.25rem;
      color: #1e293b;
    }

    .close-btn {
      background: none;
      border: none;
      color: #64748b;
      cursor: pointer;
      font-size: 1.5rem;
      padding: 0;
      width: 2rem;
      height: 2rem;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 0.25rem;
    }

    .close-btn:hover {
      color: #1e293b;
      background: #f1f5f9;
    }

    .modal-body {
      margin-bottom: 1rem;
    }

    .modal-body p {
      color: #64748b;
      margin-bottom: 1rem;
    }

    #customCharInput {
      width: 100%;
      padding: 0.75rem;
      border: 2px solid #cbd5e1;
      border-radius: 0.5rem;
      font-size: 1.5rem;
      text-align: center;
      resize: none;
      font-family: inherit;
    }

    #customCharInput:focus {
      outline: none;
      border-color: #2563eb;
    }

    .modal-footer {
      display: flex;
      gap: 0.75rem;
    }

    .modal-footer .btn {
      flex: 1;
    }

    .icon {
      width: 1.25rem;
      height: 1.25rem;
      display: inline-block;
      vertical-align: middle;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>
        <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <rect x="3" y="3" width="7" height="7"/>
          <rect x="14" y="3" width="7" height="7"/>
          <rect x="14" y="14" width="7" height="7"/>
          <rect x="3" y="14" width="7" height="7"/>
        </svg>
        24×24 Icon Editor
      </h1>
      <p class="subtitle">Create pixel-perfect icons with transparent backgrounds</p>
      <p class="save-note">💾 Your design is saved in the URL - bookmark it to save your work!</p>
    </div>

    <div class="main-grid">
      <!-- Canvas Area -->
      <div class="canvas-area">
        <div class="canvas-wrapper">
          <canvas id="displayCanvas" width="384" height="384"></canvas>
          <p class="canvas-hint">Click and drag to <span id="toolHint">draw</span> pixels</p>
        </div>
        <button class="btn btn-success" id="downloadBtn">
          <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
            <polyline points="7 10 12 15 17 10"/>
            <line x1="12" y1="15" x2="12" y2="3"/>
          </svg>
          Download PNG (24×24)
        </button>
      </div>

      <!-- Tools Panel -->
      <div>
        <!-- Tool Selection -->
        <div class="panel">
          <h3>
            <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <circle cx="13.5" cy="6.5" r=".5"/>
              <circle cx="17.5" cy="10.5" r=".5"/>
              <circle cx="8.5" cy="7.5" r=".5"/>
              <circle cx="6.5" cy="12.5" r=".5"/>
              <path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/>
            </svg>
            Tools
          </h3>
          <div class="tool-grid">
            <button class="btn btn-secondary active" id="drawBtn">
              <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <circle cx="13.5" cy="6.5" r=".5"/>
                <circle cx="17.5" cy="10.5" r=".5"/>
                <circle cx="8.5" cy="7.5" r=".5"/>
                <circle cx="6.5" cy="12.5" r=".5"/>
                <path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/>
              </svg>
              Draw
            </button>
            <button class="btn btn-secondary" id="eraseBtn">
              <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <path d="m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21"/>
                <path d="M22 21H7"/>
                <path d="m5 11 9 9"/>
              </svg>
              Erase
            </button>
          </div>
        </div>

        <!-- Color Picker -->
        <div class="panel">
          <h3>Color</h3>
          <div class="color-picker-wrapper">
            <input type="color" id="colorPicker" value="#000000">
            <input type="text" id="colorInput" value="#000000">
          </div>
          <div class="preset-colors" id="presetColors"></div>
        </div>

        <!-- Emoji Starter -->
        <div class="panel">
          <h3>Start with Emoji</h3>
          <button class="btn btn-secondary" id="toggleEmojiBtn" style="width: 100%;">Show Emojis</button>
          <div id="emojiGrid" class="emoji-grid" style="display: none;"></div>
        </div>

        <!-- Clear Button -->
        <button class="btn btn-danger" id="clearBtn">
          <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <polyline points="3 6 5 6 21 6"/>
            <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
          </svg>
          Clear Canvas
        </button>
      </div>
    </div>
  </div>

  <!-- Custom Character Modal -->
  <div class="modal" id="customCharModal">
    <div class="modal-content">
      <div class="modal-header">
        <h3>Enter Character</h3>
        <button class="close-btn" id="closeModalBtn">×</button>
      </div>
      <div class="modal-body">
        <p>Enter any emoji, letter, number, or symbol:</p>
        <textarea id="customCharInput" rows="3" placeholder="Type or paste here... (e.g., A, ⚡, 🦄)"></textarea>
      </div>
      <div class="modal-footer">
        <button class="btn btn-secondary" id="cancelModalBtn">Cancel</button>
        <button class="btn btn-primary" id="applyModalBtn">Apply</button>
      </div>
    </div>
  </div>

  <script>
    // State
    let pixels = Array(24).fill(null).map(() => Array(24).fill('transparent'));
    let currentColor = '#000000';
    let isDrawing = false;
    let currentTool = 'draw';
    let showingEmojis = false;

    // Elements
    const canvas = document.getElementById('displayCanvas');
    const ctx = canvas.getContext('2d');
    const colorPicker = document.getElementById('colorPicker');
    const colorInput = document.getElementById('colorInput');
    const drawBtn = document.getElementById('drawBtn');
    const eraseBtn = document.getElementById('eraseBtn');
    const downloadBtn = document.getElementById('downloadBtn');
    const clearBtn = document.getElementById('clearBtn');
    const toggleEmojiBtn = document.getElementById('toggleEmojiBtn');
    const emojiGrid = document.getElementById('emojiGrid');
    const presetColorsDiv = document.getElementById('presetColors');
    const toolHint = document.getElementById('toolHint');
    const customCharModal = document.getElementById('customCharModal');
    const customCharInput = document.getElementById('customCharInput');
    const closeModalBtn = document.getElementById('closeModalBtn');
    const cancelModalBtn = document.getElementById('cancelModalBtn');
    const applyModalBtn = document.getElementById('applyModalBtn');

    // Constants
    const commonEmojis = [
      '😀', '😎', '🎉', '❤️', '⭐', '🔥', '💡', '🎨',
      '🚀', '🎯', '💼', '📱', '🏠', '🎵', '🍕', '⚡',
      '✨', '🌟', '💎', '🎪', '🎭', '🎬', '📷', '🎮'
    ];

    const presetColors = [
      '#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF',
      '#FFFF00', '#FF00FF', '#00FFFF', '#FFA500', '#800080'
    ];

    // Initialize
    function init() {
      loadFromHash();
      renderCanvas();
      setupPresetColors();
      setupEmojiGrid();
      setupEventListeners();
    }

    // URL Hash persistence
    function encodePixelsToHash(pixels) {
      const colorMap = new Map();
      let colorIndex = 0;
      const encoded = [];
      
      pixels.forEach((row) => {
        row.forEach((color) => {
          if (color === 'transparent') {
            encoded.push('_');
          } else {
            if (!colorMap.has(color)) {
              colorMap.set(color, colorIndex++);
            }
            encoded.push(colorMap.get(color).toString(36));
          }
        });
      });
      
      const colorPalette = Array.from(colorMap.entries())
        .sort((a, b) => a[1] - b[1])
        .map(([color]) => color)
        .join(',');
      
      return btoa(colorPalette + '|' + encoded.join('')).replace(/=/g, '');
    }

    function decodePixelsFromHash(hash) {
      try {
        const decoded = atob(hash + '=='.slice(0, (4 - hash.length % 4) % 4));
        const [colorPalette, pixelData] = decoded.split('|');
        const colors = colorPalette ? colorPalette.split(',') : [];
        
        const newPixels = Array(24).fill(null).map(() => Array(24).fill('transparent'));
        let idx = 0;
        
        for (let y = 0; y < 24; y++) {
          for (let x = 0; x < 24; x++) {
            const char = pixelData[idx++];
            if (char !== '_') {
              const colorIndex = parseInt(char, 36);
              newPixels[y][x] = colors[colorIndex] || 'transparent';
            }
          }
        }
        
        return newPixels;
      } catch (e) {
        console.error('Failed to decode hash:', e);
        return Array(24).fill(null).map(() => Array(24).fill('transparent'));
      }
    }

    function loadFromHash() {
      const hash = window.location.hash.slice(1);
      if (hash) {
        pixels = decodePixelsFromHash(hash);
      }
    }

    function updateHash() {
      const hash = encodePixelsToHash(pixels);
      window.history.replaceState(null, '', '#' + hash);
    }

    // Render canvas
    function renderCanvas() {
      const scale = 16;
      
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      
      // Draw pixels
      pixels.forEach((row, y) => {
        row.forEach((color, x) => {
          if (color !== 'transparent') {
            ctx.fillStyle = color;
            ctx.fillRect(x * scale, y * scale, scale, scale);
          }
        });
      });
      
      // Draw grid
      ctx.strokeStyle = '#e0e0e0';
      ctx.lineWidth = 0.5;
      for (let i = 0; i <= 24; i++) {
        ctx.beginPath();
        ctx.moveTo(i * scale, 0);
        ctx.lineTo(i * scale, 24 * scale);
        ctx.stroke();
        
        ctx.beginPath();
        ctx.moveTo(0, i * scale);
        ctx.lineTo(24 * scale, i * scale);
        ctx.stroke();
      }

      updateHash();
    }

    // Canvas interaction
    function getPixelCoords(e) {
      const rect = canvas.getBoundingClientRect();
      const scale = 16;
      const x = Math.floor((e.clientX - rect.left) / (rect.width / 24));
      const y = Math.floor((e.clientY - rect.top) / (rect.height / 24));
      return { x, y };
    }

    function drawPixel(x, y) {
      if (x >= 0 && x < 24 && y >= 0 && y < 24) {
        pixels[y][x] = currentTool === 'draw' ? currentColor : 'transparent';
        renderCanvas();
      }
    }

    // Setup preset colors
    function setupPresetColors() {
      presetColors.forEach(color => {
        const btn = document.createElement('button');
        btn.className = 'color-btn';
        btn.style.backgroundColor = color;
        btn.title = color;
        btn.onclick = () => {
          currentColor = color;
          colorPicker.value = color;
          colorInput.value = color;
          updateColorSelection();
        };
        presetColorsDiv.appendChild(btn);
      });
      updateColorSelection();
    }

    function updateColorSelection() {
      document.querySelectorAll('.color-btn').forEach((btn, idx) => {
        btn.classList.toggle('active', presetColors[idx] === currentColor);
      });
    }

    // Setup emoji grid
    function setupEmojiGrid() {
      commonEmojis.forEach(emoji => {
        const btn = document.createElement('button');
        btn.className = 'emoji-btn';
        btn.textContent = emoji;
        btn.onclick = () => loadCharacter(emoji);
        emojiGrid.appendChild(btn);
      });

      // Add "more" button
      const moreBtn = document.createElement('button');
      moreBtn.className = 'emoji-btn more';
      moreBtn.innerHTML = '···';
      moreBtn.title = 'Enter custom character';
      moreBtn.onclick = () => showCustomCharModal();
      emojiGrid.appendChild(moreBtn);
    }

    // Load character onto canvas
    function loadCharacter(char) {
      const tempCanvas = document.createElement('canvas');
      tempCanvas.width = 24;
      tempCanvas.height = 24;
      const tempCtx = tempCanvas.getContext('2d');
      
      tempCtx.font = '20px Arial';
      tempCtx.textAlign = 'center';
      tempCtx.textBaseline = 'middle';
      tempCtx.fillText(char, 12, 12);
      
      const imageData = tempCtx.getImageData(0, 0, 24, 24);
      pixels = Array(24).fill(null).map(() => Array(24).fill('transparent'));
      
      for (let y = 0; y < 24; y++) {
        for (let x = 0; x < 24; x++) {
          const idx = (y * 24 + x) * 4;
          const a = imageData.data[idx + 3];
          
          if (a > 128) {
            const r = imageData.data[idx];
            const g = imageData.data[idx + 1];
            const b = imageData.data[idx + 2];
            pixels[y][x] = `rgb(${r}, ${g}, ${b})`;
          }
        }
      }
      
      renderCanvas();
      hideEmojiPicker();
    }

    // Custom character modal
    function showCustomCharModal() {
      customCharModal.classList.add('show');
      customCharInput.value = '';
      customCharInput.focus();
    }

    function hideCustomCharModal() {
      customCharModal.classList.remove('show');
    }

    function applyCustomChar() {
      const char = customCharInput.value.trim();
      if (char) {
        loadCharacter(char);
        hideCustomCharModal();
      }
    }

    // Export PNG
    function exportPNG() {
      const exportCanvas = document.createElement('canvas');
      exportCanvas.width = 24;
      exportCanvas.height = 24;
      const exportCtx = exportCanvas.getContext('2d');
      
      pixels.forEach((row, y) => {
        row.forEach((color, x) => {
          if (color !== 'transparent') {
            exportCtx.fillStyle = color;
            exportCtx.fillRect(x, y, 1, 1);
          }
        });
      });
      
      exportCanvas.toBlob((blob) => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'icon-24x24.png';
        a.click();
        URL.revokeObjectURL(url);
      });
    }

    // Clear canvas
    function clearCanvas() {
      pixels = Array(24).fill(null).map(() => Array(24).fill('transparent'));
      renderCanvas();
    }

    // Toggle emoji picker
    function toggleEmojiPicker() {
      showingEmojis = !showingEmojis;
      emojiGrid.style.display = showingEmojis ? 'grid' : 'none';
      toggleEmojiBtn.textContent = showingEmojis ? 'Hide Emojis' : 'Show Emojis';
    }

    function hideEmojiPicker() {
      showingEmojis = false;
      emojiGrid.style.display = 'none';
      toggleEmojiBtn.textContent = 'Show Emojis';
    }

    // Set tool
    function setTool(tool) {
      currentTool = tool;
      drawBtn.classList.toggle('active', tool === 'draw');
      eraseBtn.classList.toggle('active', tool === 'erase');
      toolHint.textContent = tool;
    }

    // Event listeners
    function setupEventListeners() {
      // Canvas
      canvas.addEventListener('mousedown', (e) => {
        isDrawing = true;
        const { x, y } = getPixelCoords(e);
        drawPixel(x, y);
      });

      canvas.addEventListener('mousemove', (e) => {
        if (isDrawing) {
          const { x, y } = getPixelCoords(e);
          drawPixel(x, y);
        }
      });

      canvas.addEventListener('mouseup', () => {
        isDrawing = false;
      });

      canvas.addEventListener('mouseleave', () => {
        isDrawing = false;
      });

      // Touch support
      canvas.addEventListener('touchstart', (e) => {
        e.preventDefault();
        isDrawing = true;
        const touch = e.touches[0];
        const mouseEvent = new MouseEvent('mousedown', {
          clientX: touch.clientX,
          clientY: touch.clientY
        });
        canvas.dispatchEvent(mouseEvent);
      });

      canvas.addEventListener('touchmove', (e) => {
        e.preventDefault();
        if (isDrawing) {
          const touch = e.touches[0];
          const mouseEvent = new MouseEvent('mousemove', {
            clientX: touch.clientX,
            clientY: touch.clientY
          });
          canvas.dispatchEvent(mouseEvent);
        }
      });

      canvas.addEventListener('touchend', (e) => {
        e.preventDefault();
        isDrawing = false;
      });

      // Color picker
      colorPicker.addEventListener('input', (e) => {
        currentColor = e.target.value;
        colorInput.value = e.target.value;
        updateColorSelection();
      });

      colorInput.addEventListener('input', (e) => {
        const color = e.target.value;
        if (/^#[0-9A-Fa-f]{6}$/.test(color)) {
          currentColor = color;
          colorPicker.value = color;
          updateColorSelection();
        }
      });

      // Tools
      drawBtn.addEventListener('click', () => setTool('draw'));
      eraseBtn.addEventListener('click', () => setTool('erase'));

      // Actions
      downloadBtn.addEventListener('click', exportPNG);
      clearBtn.addEventListener('click', clearCanvas);
      toggleEmojiBtn.addEventListener('click', toggleEmojiPicker);

      // Modal
      closeModalBtn.addEventListener('click', hideCustomCharModal);
      cancelModalBtn.addEventListener('click', hideCustomCharModal);
      applyModalBtn.addEventListener('click', applyCustomChar);
      
      customCharModal.addEventListener('click', (e) => {
        if (e.target === customCharModal) {
          hideCustomCharModal();
        }
      });

      customCharInput.addEventListener('keydown', (e) => {
        if (e.key === 'Enter' && !e.shiftKey) {
          e.preventDefault();
          applyCustomChar();
        }
      });
    }

    // Start the app
    init();
  </script>
</body>
</html>
